
// Author: Rafal Pielech 
// E-mail: rafalpielech@hotmail.com
// Date:   2003.08.31

#ifndef SIMPLE_VECTOR
#define SIMPLE_VECTOR

#include <math.h>

template < class ElType >
class Simple_Vector
{
      private:
               ElType Elements[4];
               
      public:
               Simple_Vector( void );
               Simple_Vector( const ElType x , const ElType y , const ElType z );
               
               ElType GetElement( const short Coord ) const;
               
               void  SetElement( const short Coord , const ElType Value );
               
               ElType Length( void ) const;
               ElType AngleVectAxis( const char Axis ) const;
               
               void  Print( void ); 

        friend Simple_Vector<ElType> operator - ( const Simple_Vector<ElType> left , const Simple_Vector<ElType> right )
               {
                     Simple_Vector<ElType> Result;
      
                     Result.Elements[0] = ( left.Elements[0] - right.Elements[0] );
                     Result.Elements[1] = ( left.Elements[1] - right.Elements[1] );
                     Result.Elements[2] = ( left.Elements[2] - right.Elements[2] );
      
                     return Result;
               }
        
               Simple_Vector<ElType> operator + ( const Simple_Vector<ElType> Vec );
               
               Simple_Vector<ElType> operator = ( const Simple_Vector<ElType> Vec );
               
               void CrossProduct( Simple_Vector<ElType> Vec );
};


//---------------------------------------------------------------------------------------

template < class ElType >
Simple_Vector<ElType> :: Simple_Vector( void )
{
      Elements[0] = Elements[1] = Elements[2] = 0.0;
      
      Elements[3] = 1.0;
}

//---------------------------------------------------------------------------------------

template < class ElType >
Simple_Vector<ElType> :: Simple_Vector( const ElType x , const ElType y , const ElType z )
{
      Elements[0] = x;
      Elements[1] = y;
      Elements[2] = z;
      Elements[3] = 1.0;
}

//---------------------------------------------------------------------------------------

template < class ElType >
ElType
Simple_Vector<ElType> :: GetElement( const short Coord ) const
{
      if( (Coord < 0)||(Coord > 3) )
      {
            return 0.0;
      }
      else
      {
            return Elements[ Coord ];
      }
}

//---------------------------------------------------------------------------------------

template < class ElType >
void
Simple_Vector<ElType> :: SetElement( const short Coord , const ElType Value )
{
      if( (Coord < 0)||(Coord > 3) )
      {
            return;
      }
      else
      {
            Elements[ Coord ] = Value;
      }
}

//---------------------------------------------------------------------------------------

template < class ElType >
ElType
Simple_Vector<ElType> :: Length( void ) const
{
      ElType squares = (Elements[0] * Elements[0]) + (Elements[1] * Elements[1]) + (Elements[2] * Elements[2]);
      
      double result = sqrt( static_cast<double>(squares) );
      
      return ( static_cast<ElType>(result) );
}

//---------------------------------------------------------------------------------------

template < class ElType >
ElType
Simple_Vector<ElType> :: AngleVectAxis( const char Axis ) const
{
    ElType Angle;
      
      switch( Axis )
      {
            case 'x':
                      Angle = static_cast < ElType >( (180/M_PI) * acos( (double)Elements[0]/Length()) );
                      break;

            case 'y':
                      Angle = static_cast < ElType >( (180/M_PI) * acos( (double)Elements[1]/Length()) );
                      break;

            case 'z':
                      Angle = static_cast < ElType >( (180/M_PI) * acos( (double)Elements[2]/Length()) );
                      break;
      }
      
    return Angle;
}

//---------------------------------------------------------------------------------------

template < class ElType >
Simple_Vector<ElType>
Simple_Vector<ElType> :: operator + ( const Simple_Vector<ElType> Vec )
{
      Simple_Vector<ElType> Result;
      
      Result.SetElement( 0 , (Elements[0] + Vec.GetElement(0)) );
      Result.SetElement( 1 , (Elements[1] + Vec.GetElement(1)) );
      Result.SetElement( 2 , (Elements[2] + Vec.GetElement(2)) );
      
      return Result;
}

//---------------------------------------------------------------------------------------

template < class ElType >
void
Simple_Vector<ElType> :: Print( void )
{
      cout << "\n[ " << Elements[0] << " " << Elements[1] << " " << Elements[2] << " " << Elements[3] << " ]\n" << endl;
}


//---------------------------------------------------------------------------------------

template < class ElType >
Simple_Vector<ElType>
Simple_Vector<ElType> :: operator = ( const Simple_Vector<ElType> Vec )
{
      Elements[0] = Vec.GetElement(0);
      Elements[1] = Vec.GetElement(1);
      Elements[2] = Vec.GetElement(2);
      Elements[3] = Vec.GetElement(3);
      
      return (*this);
}

//---------------------------------------------------------------------------------------

template < class ElType >
void
Simple_Vector<ElType> :: CrossProduct( Simple_Vector<ElType> Vec )
{
 
 ElType x = Elements[0];
 ElType y = Elements[1];
 ElType z = Elements[2];
 
 ElType x__ = Vec.GetElement(0);
 ElType y__ = Vec.GetElement(1);
 ElType z__ = Vec.GetElement(2);
 
    Elements[0] = y * z__ - y__ * y;
    Elements[1] = x__ * z - y * z__;
    Elements[2] = x * y__ - x__ * y;
 
}
//---------------------------------------------------------------------------------------
#endif